using System;
using System.Collections;
using System.Configuration;
using System.Globalization;
using System.Threading;
using log4net;
using Sedna.Core.Security;

namespace Sedna.Core.Globalization
{
	/// <summary>
	/// message manager that uses a hashtable (key=value) to represent a mapping.
	/// first it uses a hashtable to locate a second level hashtable for particular culture.
	/// This means that first it tries to lookup a message bundle for a specified (or defined in a thread)
	/// culture by its name (e.g. 'en-US' or 'ru-RU'). If no hashtable (resource bundle) can be located for a particular culture
	/// a bundle with the name='neutral' is used. This one should contain english resources by default.
	/// Please note that the bundle keys (the one that hold the whole bundle for a particular culture)
	/// must be exactly the same as it definen in a .Net documentation for particular cultires.
	/// no generic values are possible, e.g. it would be a mistake to name a bundle 'en' instead of 'en-US'.
	/// </summary>
	public class HashtableMessageManager : IMessageManager
	{

		private ILog log = LogManager.GetLogger(typeof(HashtableMessageManager));

		private IDictionary culture2messages = new Hashtable();

		public IDictionary Messages
		{
			set
			{
				for(IDictionaryEnumerator de = value.GetEnumerator(); de.MoveNext();)
				{
					string infoName = (string)de.Key;
					//CultureInfo infoKey = infoName=="neutral"?CultureInfo.InvariantCulture:new CultureInfo(infoName);
					CultureInfo infoKey = (infoName == "neutral") ? CultureInfo.InvariantCulture : CultureInfo.CreateSpecificCulture(infoName);
					culture2messages[infoKey] = de.Value;
				}
			}
		}


		public string GetMessage(string key)
		{
			return GetMessage(key, Thread.CurrentThread.CurrentCulture);
		}
		public string GetMessage(string key, string defaultValue)
		{
		    SednaWorkPrincipal principal = Thread.CurrentPrincipal as SednaWorkPrincipal;
			return GetMessage(key, principal==null?Thread.CurrentThread.CurrentCulture:principal.Culture, defaultValue);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="key">can be null, the method returns null if a key is null</param>
		/// <param name="cultureInfo">must not be null</param>
		/// <returns>
		/// returns a localized message for a specified culture or for 
		/// a default culture if target culture resource bundle 
		/// contains no corresponding message. if message is found neither in specified culture nor in neutral, the methos returns null
		/// </returns>
		public string GetMessage(string key, CultureInfo cultureInfo)
		{
			if (key==null)
			{
				return null;
			}
			IDictionary messages = (IDictionary)culture2messages[cultureInfo];
			if(messages != null)
			{
				string value = (string)messages[key];
				if(value != null)
				{
					return value;
				}
			}
			messages = (IDictionary)culture2messages[CultureInfo.InvariantCulture];
			if(messages == null)
			{
				throw new Sedna.Core.Controller.ControllerConfigurationException("messages for default culture must be set");
			}
			
			string message = (string)messages[key];

			if (message==null&&log.IsDebugEnabled)
			{
				log.Debug("Localized message not found for key \""+key+"\"");	
			}

			return message;
		}

		/// <summary>
		/// the same as above but the method returns a specified default value
		/// in case of a mapped one is not found
		/// </summary>
		/// <param name="key">unique message key</param>
		/// <param name="cultureInfo">specific culture</param>
		/// <param name="defaultValue">default value that is returned in case of the above method returns null</param>
		/// <returns>either localized (or neutral) message or a default value if the former is not found</returns>
		public string GetMessage(string key, CultureInfo cultureInfo, string defaultValue)
		{
			string message = GetMessage(key, cultureInfo);
			if (message==null&&log.IsDebugEnabled)
			{
				log.Debug("Localized message not found for key \""+key+"\". Use default value \""+defaultValue+"\"!!! ");	
			}
			return message!=null?message:defaultValue;
		}

	}
}
